package br.com.petsis.funcionalidades.manterEmpresa;

import java.awt.Color;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.faces.model.SelectItem;
import javax.imageio.ImageIO;
import javax.persistence.EntityManager;
import javax.persistence.NoResultException;

import nl.captcha.Captcha;
import nl.captcha.backgrounds.GradiatedBackgroundProducer;

import org.jboss.seam.ScopeType;
import org.jboss.seam.annotations.In;
import org.jboss.seam.annotations.Name;
import org.jboss.seam.annotations.Out;
import org.jboss.seam.annotations.Scope;
import org.jboss.seam.faces.FacesMessages;
import org.jboss.seam.international.StatusMessage.Severity;

import br.com.petsis.conversores.ConversorCnpj;
import br.com.petsis.entity.Empresa;
import br.com.petsis.entity.Perfil;
import br.com.petsis.entity.PerfilFuncionalidade;
import br.com.petsis.entity.Raca;
import br.com.petsis.entity.Usuario;
import br.com.petsis.utilitarios.UtilDate;
import br.com.petsis.utilitarios.UtilMail;
import br.com.petsis.utilitarios.UtilString;
import br.com.petsis.utilitarios.UtilUfs;

@Name("manterEmpresaController")
@Scope(ScopeType.CONVERSATION)
//@Restrict(value="#{identity.hasRole('Administrador')}")
public class ManterEmpresaController {
	
	private static final String QRY_EMPRESAS = "select e from Empresa e where e.flgAtivo = 'T'";
	private static final String QRY_EMPRESAS_VALIDADE = "select e from Empresa e where e.flgAtivo = 'T' order by e.dtaValidade";
	private static final String QRY_USUARIO_EMAIL = "select u from Usuario u where u.flgAtivo = 'T' and UPPER(u.cliente.dscEmail) = UPPER(:email)";
	private static final String QRY_EMPRESA_EMAIL = "select u from Usuario u where u.flgAtivo = 'T' and UPPER(u.empresa.dscEmail) = UPPER(:email) and u.empresa.flgAtivo = 'T' and u.empresa.idEmpresa != :idEmpresa";
	private static final String QRY_EMPRESA_NOVA_EMAIL = "select u from Usuario u where u.flgAtivo = 'T' and UPPER(u.empresa.dscEmail) = UPPER(:email) and u.empresa.flgAtivo = 'T'";
	private static final String QRY_EMPRESA_CNPJ = "select e from Empresa e where e.flgAtivo = 'T' and e.dscCnpj = :cnpj and e.idEmpresa != :idEmpresa";
	private static final String QRY_EMPRESA_NOVA_CNPJ = "select e from Empresa e where e.flgAtivo = 'T' and e.dscCnpj = :cnpj";
	
	@In(create=true)
	private EntityManager entityManager;
	
	private List<Empresa> listaEmpresas;
	
	private List<Empresa> listaEmpresasValidade;
	
	private List<SelectItem> listaUfs;
	
	private Empresa empresaEdicao;
	
	private Usuario usuarioEdicao;
	
	private boolean selecionadoTodos;
	
	private String captcha;
	
	private String resposta;
	
	@In(required = false)
	@Out(required = false, scope = ScopeType.SESSION)
	private Empresa empresaSessao;
	
	public void onLoad(){
		
	}
	
	public void onLoadMinhaEmpresa(){
		if(empresaSessao != null){
			empresaEdicao = empresaSessao;
		}else{
			FacesMessages.instance().add(Severity.ERROR,"Somente usuários de empresas podem acessar este recurso.");
		}
	}
	
	public void onLoadList(){
		empresaEdicao = new Empresa();
	}
	
	public void excluir(){
		List<Empresa> listaRemocao = new ArrayList<Empresa>();
		for(Empresa e : getListaEmpresas()){
			if(e.isSelecionado()){
				e.setFlgAtivo('F');
				entityManager.merge(e);
				listaRemocao.add(e);
			}
		}
		entityManager.flush();
		getListaEmpresas().removeAll(listaRemocao);
		setSelecionadoTodos(false);
	}
	
	public void salvarMinhaEmpresa(){
		if(!validaEmpresa(empresaEdicao)){
			return;
		}
		empresaSessao = entityManager.merge(empresaEdicao);
		entityManager.flush();
		FacesMessages.instance().add(Severity.INFO,"Dados alterados com sucesso.");
	}
	
	public String salvar(){
		if(!validaEmpresa(getEmpresaEdicao())){
			return null;
		}
		empresaEdicao.setFlgAtivo('T');
		if(empresaEdicao.getDtaCadastro() == null){
			empresaEdicao.setDtaCadastro(new Date());
		}
		Empresa empresaSalva = entityManager.merge(empresaEdicao);
		if(!getListaEmpresas().contains(empresaSalva)){
			getListaEmpresas().add(empresaSalva);
		}
		empresaEdicao = new Empresa();
		entityManager.flush();
		FacesMessages.instance().add(Severity.INFO,"Empresa salva com sucesso.");
		return "persisted";
	}
	
	public boolean validaCaptcha(){
		
		if(!resposta.equalsIgnoreCase(getCaptcha())){
			FacesMessages.instance().add(Severity.ERROR,"Código de validação inválido.");
			return false;
		}
		return true;
	}
	
	public void criarRacasNovaEmpresa(Empresa empresa){
		List<Raca> racas = entityManager.createQuery("select r from Raca r where r.empresa is null and r.flgAtivo = 'T'").getResultList();
		for(Raca r : racas){
			Raca novaRaca = new Raca(r);
			novaRaca.setEmpresa(empresa);
			entityManager.merge(novaRaca);
		}
		entityManager.flush();
	}
	
	public void criarPerfilClienteEmpresa(Empresa empresa){
		try{
			Perfil perfil = (Perfil)entityManager.createQuery("select p from Perfil p where UPPER(p.dscNome) = 'CLIENTE' and p.flgAtivo = 'T' and p.empresa is null")
				.getSingleResult();
			List<PerfilFuncionalidade> funcionalidades = entityManager.createQuery("select p from PerfilFuncionalidade p where p.perfil.idPerfil = :idPerfil")
				.setParameter("idPerfil", perfil.getIdPerfil())
				.getResultList();
			Perfil novoPerfil = new Perfil(perfil);
			novoPerfil.setEmpresa(empresa);
			Perfil perfilSalvo = entityManager.merge(novoPerfil);
			PerfilFuncionalidade novaFuncionalidade;
			for(PerfilFuncionalidade pf : funcionalidades){
				novaFuncionalidade = new PerfilFuncionalidade(pf);
				novaFuncionalidade.setPerfil(perfilSalvo);
				entityManager.merge(novaFuncionalidade);
			}
			entityManager.flush();
		}catch(NoResultException e){
			
		}
	}
	
	public String salvarEmpresaCliente(){
		if(!validaEmpresa(getEmpresaEdicao())){
			return null;
		}
		if(!validaCaptcha()){
			return null;
		}
		if(recuperaPerfilEmpresa() == null){
			FacesMessages.instance().add(Severity.INFO,"Perfil de EMPRESA ainda não cadastrado. Entre em contato com o administrador do sistema.");
			return null;
		}
		empresaEdicao.setFlgAtivo('T');
		empresaEdicao.setDtaValidade(UtilDate.getDataAcrescidaEmDias(new Date(), 30));
		if(empresaEdicao.getDtaCadastro() == null){
			empresaEdicao.setDtaCadastro(new Date());
		}
		Empresa empresaSalva = entityManager.merge(empresaEdicao);
		getUsuarioEdicao().setEmpresa(empresaSalva);
		getUsuarioEdicao().setDscNome(empresaSalva.getDscNomeResponsavel());
		getUsuarioEdicao().setDscUsuario(empresaSalva.getDscEmail());
		getUsuarioEdicao().setFlgAtivo('T');
		getUsuarioEdicao().setPerfil(recuperaPerfilEmpresa());
		String senha = gerarNovaSenha();
		getUsuarioEdicao().setDscSenha(UtilString.md5(senha));
		entityManager.merge(getUsuarioEdicao());
		
		if(!getListaEmpresas().contains(empresaSalva)){
			getListaEmpresas().add(empresaSalva);
		}
		enviarEmailNovaSenha(empresaSalva.getDscEmail(), senha);
		enviarEmailNotificacao();
		empresaEdicao = new Empresa();
		usuarioEdicao = new Usuario();
		entityManager.flush();
		criarPerfilClienteEmpresa(empresaSalva);
		criarRacasNovaEmpresa(empresaSalva);
		FacesMessages.instance().add(Severity.INFO,"Empresa salva com sucesso. Você já pode utilizar o sistema por 30 dias gratuitos.");
		return "persisted";
	}
	
	public void salvarTodasEmpresas(){
		for(Empresa e : getListaEmpresasValidade()){
			entityManager.merge(e);
		}
		entityManager.flush();
		FacesMessages.instance().add(Severity.INFO,"Empresas salvas com sucesso.");
	}
	
	public void enviarEmailNovaSenha(String destinatario, String novaSenha){
		try {
			StringBuilder texto = new StringBuilder();
			texto.append("<center><img src=\"cid:image\">");
			texto.append("<br/><br/><b>Este é um e-mail automático, por favor não responda.</b><br/>");
			texto.append("<br/><br/>Bem vindo ao PetSis - Sistema de Pet Shop.");
			texto.append("<br/><br/>Sua nova senha de acesso é:");
			texto.append(novaSenha);
			texto.append("<br/><br/><u>Obs: Altere a sua senha no primeiro acesso.</u>");
			texto.append("<br/><br/><br/>Sistema PetSis</center>");
			UtilMail.enviarEmailAssincrono(texto.toString(), destinatario, "PETSIS: BEM VINDO!");
			FacesMessages.instance().add(Severity.INFO,"Foi enviado um e-mail contendo a nova senha.");
		} catch (Exception e) {
			FacesMessages.instance().add(Severity.ERROR,"Não foi possível enviar o e-mail com a nova senha. Verifique o e-mail informado ou tente novamente mais tarde.");
			e.printStackTrace();
		}
	}
	
	public void enviarEmailNotificacao(){
    	SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy HH:mm");
    	StringBuilder texto = new StringBuilder();
    	texto.append("<center><img src=\"cid:image\"><br/>");
    	texto.append("<b>Atenção</b><br/>");
    	texto.append("Uma nova empresa cadastrou-se no sistema.<br/><br/>Detalhes:<br/><table>");
    	texto.append("<tr><td><b>Razão social:</b></td><td> ");
    	texto.append(getEmpresaEdicao().getDscRazaoSocial());
    	texto.append("</td></tr>");
    	texto.append("<tr><td><b>Nome fantasia:</b></td><td> ");
    	texto.append(getEmpresaEdicao().getDscNomeFantasia());
    	texto.append("</td></tr>");
    	texto.append("<tr><td><b>Cnpj:</b></td><td> ");
    	texto.append(ConversorCnpj.mascara(getEmpresaEdicao().getDscCnpj()));
    	texto.append("</td></tr>");
    	texto.append("<tr><td><b>Nome responsável:</b></td><td> ");
    	texto.append(getEmpresaEdicao().getDscNomeResponsavel());
    	texto.append("</td></tr>");
    	texto.append("<tr><td><b>E-mail:</b></td><td> ");
    	texto.append(getEmpresaEdicao().getDscEmail());
    	texto.append("</td></tr>");
    	texto.append("<tr><td><b>Data de cadastramento:</b></td><td> ");
    	texto.append(sdf.format(new Date()));
    	texto.append("</td></tr>");
    	texto.append("<tr><td><b>Telefone(s):</b></td><td> ");
    	texto.append(getEmpresaEdicao().getDscTelefone1());
    	texto.append("/");
    	texto.append(getEmpresaEdicao().getDscTelefone2());
    	texto.append("</td></tr>");
    	texto.append("<tr><td><b>Endereço:</b></td><td> ");
    	texto.append(getEmpresaEdicao().getDscEndereco());
    	texto.append(", ");
    	texto.append(getEmpresaEdicao().getDscCidade());
    	texto.append("</td></tr></table>");
    	texto.append("<br/><br/><br/>Sistema PetSis</center>");
    	
    	String assunto = "PETSIS: Nova empresa cadastrada no sistema";
    	
    	try {
			UtilMail.enviarEmailAssincrono(texto.toString(), UtilMail.EMAIL_PADRAO_PET, assunto);
		} catch (Exception e) {
			e.printStackTrace();
		}
		
    }
	
	public String gerarNovaSenha(){
		Long i = (long) (10000000 + Math.random() * 8999999l);
		return i.toString();
	}
	
	public Perfil recuperaPerfilCliente(){
		try{
			return (Perfil)entityManager.createQuery("select p from Perfil p where UPPER(p.dscNome) like UPPER(:nome)")
				.setParameter("nome", "cliente")
				.getSingleResult();
		}catch(NoResultException e){
			return null;
		}
	}
	
	public Perfil recuperaPerfilEmpresa(){
		try{
			return (Perfil)entityManager.createQuery("select p from Perfil p where UPPER(p.dscNome) like UPPER(:nome)")
				.setParameter("nome", "empresa")
				.getSingleResult();
		}catch(NoResultException e){
			return null;
		}
	}
	
	public String recuperaCorBackground(Empresa empresa){
		if(UtilDate.data1MenorOuIgualQueData2(empresa.getDtaValidade(),new Date())){
			return "red";
		}else if(UtilDate.data1IgualData2(UtilDate.getDataAcrescidaEmDias(new Date(), 1), empresa.getDtaValidade())){
			return "yellow";
		}else{
			return "white";
		}
	}
	
	public String editar(Empresa empresa){
		empresaEdicao = empresa;
		return "editar";
	}

	public boolean isSelecionadoTodos() {
		return selecionadoTodos;
	}

	public void setSelecionadoTodos(boolean selecionadoTodos) {
		this.selecionadoTodos = selecionadoTodos;
	}
	
	public String getCaptcha() {
		return captcha;
	}

	public void setCaptcha(String captcha) {
		this.captcha = captcha;
	}

	public String getResposta() {
		return resposta;
	}

	public void setResposta(String resposta) {
		this.resposta = resposta;
	}

	public void selecionaTodos(){
		for(Empresa c : getListaEmpresas()){
			if(isSelecionadoTodos()){
				c.setSelecionado(true);
			}else{
				c.setSelecionado(false);
			}
		}
	}
	
	public void selecionaTodosPainel(){
		for(Empresa c : getListaEmpresasValidade()){
			if(isSelecionadoTodos()){
				c.setSelecionado(true);
			}else{
				c.setSelecionado(false);
			}
		}
	}
	
	public List<Empresa> getListaEmpresas() {
		if (listaEmpresas == null) {
			listaEmpresas = entityManager.createQuery(QRY_EMPRESAS).getResultList();
		}
		return listaEmpresas;
	}

	public void setListaEmpresas(List<Empresa> listaEmpresas) {
		this.listaEmpresas = listaEmpresas;
	}

	public List<Empresa> getListaEmpresasValidade() {
		if (listaEmpresasValidade == null) {
			listaEmpresasValidade = entityManager.createQuery(QRY_EMPRESAS_VALIDADE).getResultList();
		}
		return listaEmpresasValidade;
	}

	public void setListaEmpresasValidade(List<Empresa> listaEmpresasValidade) {
		this.listaEmpresasValidade = listaEmpresasValidade;
	}

	public List<SelectItem> getListaUfs() {
		if (listaUfs == null) {
			listaUfs = new ArrayList<SelectItem>();
			listaUfs.add(new SelectItem(null,"Selecione"));
			for(String uf : UtilUfs.recuperaListaUfs()){
				listaUfs.add(new SelectItem(uf,uf));
			}
		}
		return listaUfs;
	}

	public void setListaUfs(List<SelectItem> listaUfs) {
		this.listaUfs = listaUfs;
	}

	public Empresa getEmpresaEdicao() {
		if (empresaEdicao == null) {
			empresaEdicao = new Empresa();
		}
		return empresaEdicao;
	}

	public void setEmpresaEdicao(Empresa empresaEdicao) {
		this.empresaEdicao = empresaEdicao;
	}

	public Usuario getUsuarioEdicao() {
		if (usuarioEdicao == null) {
			usuarioEdicao = new Usuario();
		}
		return usuarioEdicao;
	}

	public void setUsuarioEdicao(Usuario usuarioEdicao) {
		this.usuarioEdicao = usuarioEdicao;
	}

	public String novaEmpresa(){
		return "novo"; 
	}
	
	public String cancelar(){
		empresaEdicao = new Empresa();
		return "voltar";  
	}
	
	public boolean validaEmpresa(Empresa empresa){
		try{
			entityManager.createQuery(QRY_USUARIO_EMAIL)
				.setParameter("email", empresa.getDscEmail())
				.getSingleResult();
			FacesMessages.instance().add(Severity.ERROR,"E-mail já cadastrado.");
			return false;
		}catch(NoResultException e){
			try{
				if(empresa.getIdEmpresa() != null){
					entityManager.createQuery(QRY_EMPRESA_EMAIL)
						.setParameter("email", empresa.getDscEmail())
						.setParameter("idEmpresa", empresa.getIdEmpresa())
						.getSingleResult();
					FacesMessages.instance().add(Severity.ERROR,"E-mail já cadastrado.");
					return false;
				}else{
					entityManager.createQuery(QRY_EMPRESA_NOVA_EMAIL)
						.setParameter("email", empresa.getDscEmail())
						.getSingleResult();
					FacesMessages.instance().add(Severity.ERROR,"E-mail já cadastrado.");
					return false;
				}
			}catch(NoResultException e1){
				try{
					if(empresa.getIdEmpresa() != null){
						entityManager.createQuery(QRY_EMPRESA_CNPJ)
							.setParameter("cnpj", empresa.getDscCnpj())
							.setParameter("idEmpresa", empresa.getIdEmpresa())
							.getSingleResult();
						FacesMessages.instance().add(Severity.ERROR,"Empresa já cadastrada.");
						return false;
					}else{
						entityManager.createQuery(QRY_EMPRESA_NOVA_CNPJ)
							.setParameter("cnpj", empresa.getDscCnpj())
							.getSingleResult();
						FacesMessages.instance().add(Severity.ERROR,"Empresa já cadastrada.");
						return false;
						
					}
				}catch(NoResultException e2){
					return true;
				}
			}
		}
	}
	
	public byte[] recuperaImagemCaptcha(){
		Captcha captcha = new Captcha.Builder(200, 60)
	        .addText()
	        .addBackground(new GradiatedBackgroundProducer(Color.WHITE, Color.WHITE))
	        .gimp()
//	        .addNoise()
//	        .addBorder()
	        .build();
		resposta = captcha.getAnswer();
		try {
			ByteArrayOutputStream baos = new ByteArrayOutputStream();
			ImageIO.write( captcha.getImage(), "jpg", baos );
			baos.flush();
			byte[] imageInByte = baos.toByteArray();
			baos.close();
			return imageInByte;
		} catch (IOException e) {
			e.printStackTrace();
		}
		return null;
	}
	
}
